package com.katze.common;

import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.buf.HexUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.beans.Introspector;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

public class CommonUtils {

    /**
     * SHA1 加密
     * @param data 原始数据
     * @param key 密钥
     * @return 加密数据
     */
    public static String hmacSha1(String data, String key) {
        try {
            SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return HexUtils.toHexString(rawHmac);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取本地所有IP地址
     */
    public static Map<String, String> getLocalAddress() {
        Map<String, String> map = new LinkedHashMap<>();
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                //isUp判断是否是启动状态, isVirtual 判断是否是虚拟Ip, isLoopback 判断是否是子网络接口
                if (networkInterface.isUp() && !networkInterface.isVirtual() && !networkInterface.isLoopback()) {
                    Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        InetAddress inetAddress = addresses.nextElement();
                        if (inetAddress instanceof Inet4Address) {
                            String hostAddress = inetAddress.getHostAddress();
                            map.put(networkInterface.getDisplayName(), hostAddress);
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 删除目录 (包括非空目录)
     * @param dir 目录路径
     * @throws IOException 删除异常
     */
    public static void deleteDir(Path dir) throws IOException {
        if (Files.exists(dir)) {
            Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                }
                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    Files.delete(dir);
                    return FileVisitResult.CONTINUE;
                }
            });
        }
    }

    /**
     * 首字母转小写
     * @param value 数据值
     */
    public static String lowerFirst(String value) {
        if (StringUtils.isNotBlank(value)){
            char[] cs=value.toCharArray();
            if (Character.isUpperCase(cs[0])){
                cs[0]+=32;
            }
            return String.valueOf(cs);
        }
        return value;
    }

    /**
     * 文件大小格式转换
     * @param size 文件大小
     */
    public static String sizeFormat(long size) {
        if (size <= 0) {
            return "0";
        }
        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,###.##").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }

    /**
     * 读取Jar包中MANIFEST.MF清单文件信息
     * @param file Jar包文件
     */
    public static Attributes loadJarManifest(File file) {
        Attributes attributes = null;
        if (file.exists() && file.getName().endsWith(".jar")) {
            try (JarFile jarFile = new JarFile(file)) {
                Manifest manifest = jarFile.getManifest();
                attributes = manifest.getMainAttributes();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return attributes;
    }

    /**
     * 通过lambda表达式获取字段名称
     * @param lambda 对象字段的lambda表达式
     */
    public static String getLambdaFieldName(Serializable lambda) {
        try {
            Method method = lambda.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            SerializedLambda serializedLambda = (SerializedLambda) method.invoke(lambda);
            String name = serializedLambda.getImplMethodName();
            name = name.startsWith("is")? name.substring(2):name.substring(3);
            return Introspector.decapitalize(name);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }
}
